package com.yunxin.admin.system.application.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yunxin.admin.system.application.MenuQueryService;
import com.yunxin.admin.system.application.UserQueryService;
import com.yunxin.admin.system.application.assembler.BasePageAssembler;
import com.yunxin.admin.system.application.assembler.UserAssembler;
import com.yunxin.admin.system.application.command.UserMerchantPageCommand;
import com.yunxin.admin.system.application.command.UserPageCommand;
import com.yunxin.admin.system.application.dto.*;
import com.yunxin.admin.system.application.dto.base.BasePageDTO;
import com.yunxin.admin.system.domain.model.user.User;
import com.yunxin.admin.system.domain.model.user.UserRepository;
import com.yunxin.admin.system.domain.model.user.UserSimple;
import com.yunxin.admin.system.infra.common.constant.SecurityConstants;
import com.yunxin.admin.system.infra.common.constant.SystemConstants;
import com.yunxin.admin.system.infra.framework.security.util.SecurityUtils;
import com.yunxin.admin.system.infra.persistence.entity.SysRoleDO;
import com.yunxin.admin.system.infra.persistence.entity.SysUserDO;
import com.yunxin.admin.system.infra.persistence.entity.SysUserMerchantDO;
import com.yunxin.admin.system.infra.persistence.entity.query.condition.UserMerchantPageCondition;
import com.yunxin.admin.system.infra.persistence.entity.query.condition.UserPageCondition;
import com.yunxin.admin.system.infra.persistence.entity.query.result.*;
import com.yunxin.admin.system.infra.persistence.mapper.SysRoleMapper;
import com.yunxin.admin.system.infra.persistence.mapper.SysUserMapper;
import com.yunxin.admin.system.infra.persistence.mapper.SysUserMerchantMapper;
import com.yunxin.core.admin.domain.AdminDept;
import com.yunxin.core.admin.domain.AdminUser;
import com.yunxin.core.admin.domain.AdminUserTeamShip;
import com.yunxin.core.admin.service.*;
import com.yunxin.core.application.command.user.AddUserTeamCommand;
import com.yunxin.core.application.dto.merchant.MerchantUserAccountDTO;
import com.yunxin.core.application.service.MerchantQueryAdminService;
import com.yunxin.core.application.service.UserTeamShipService;
import com.yunxin.core.application.service.impl.TeamServiceImpl;
import com.yunxin.core.domain.model.team.Team;
import com.yunxin.core.wechat.domain.WechatInfo;
import com.yunxin.core.wechat.domain.WechatInfoTeam;
import com.yunxin.core.wechat.domain.WechatUserSys;
import com.yunxin.core.wechat.service.WechatInfoService;
import com.yunxin.core.wechat.service.WechatInfoTeamService;
import com.yunxin.core.wechat.service.WechatUserSysService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.yunxin.core.domain.model.team.UserTeamShip;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static java.util.Arrays.stream;

/**
 * @author zero°
 * @since 2023-07-11
 */
@Service
@RequiredArgsConstructor
public class UserQueryServiceImpl implements UserQueryService {

    private final SysUserMapper sysUserMapper;

    private final SysUserMerchantMapper sysUserMerchantMapper;

    private final UserRepository userRepository;

    private final UserAssembler userAssembler;

    private final BasePageAssembler basePageAssembler;

    private final MenuQueryService menuQueryService;

    private final SysRoleMapper sysRoleMapper;

    private final RedisTemplate redisTemplate;

    private final MerchantQueryAdminService merchantQueryAdminService;

    @Autowired
    TeamServiceImpl teamService;

    @Autowired
    private WechatUserSysService wechatUserSysService;


    @Autowired
    private UserTeamShipService userTeamShipService;

    @Autowired
    private AdminUserService adminUserService;

    @Autowired
    private AdminUserTeamShipService adminUserTeamShipService;

    @Autowired
    private AdminDeptService adminDeptService;
    @Autowired
    private WechatInfoTeamService wechatInfoTeamService;
    @Autowired
    private WechatInfoService wechatInfoService;


    @Override
    public Page<UserPageDTO> getUserPage(UserPageCommand command) {
        BasePageDTO basePageDTO = basePageAssembler.formBasePageCommand(command);
        UserPageCondition condition = userAssembler.formUserPageCondition(command);
        condition.setRoleCodeList(SecurityUtils.X.getRoleCodeList());
        LambdaQueryWrapper<SysRoleDO> sysRoleDOLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sysRoleDOLambdaQueryWrapper.eq(SysRoleDO::getCode,command.getRoleCode());
        SysRoleDO sysRoleDO = sysRoleMapper.selectOne(sysRoleDOLambdaQueryWrapper);
        if(sysRoleDO!=null){
            condition.setRoleId(sysRoleDO.getId());
        }
        // 参数构建
        int pageNum = basePageDTO.getPageNum();
        int pageSize = basePageDTO.getPageSize();
        Page<User> page = new Page<>(pageNum, pageSize);

        // 查询数据
        Page<UserPageResult> userPage = sysUserMapper.getUserPage(page, condition);

        // 将userPage中teamIds为空的数据排除
//        userPage.getRecords().removeIf(userPageResult -> StringUtils.isBlank(userPageResult.getTeamIds()));

//        Page<UserPageDTO> userPageDTO = userAssembler.toUserPageDTO(userPage);

        Page<UserPageDTO> userPageDTO = new Page<>();
        // 使用stream流将UserPageResult转换为UserPageDTO并封装成一个集合
        List<UserPageDTO> collect = userPage.getRecords().stream().map(userPageResult -> {
            UserPageDTO pageDTO = new UserPageDTO();
            BeanUtils.copyProperties(userPageResult, pageDTO);
            LambdaQueryWrapper<SysUserMerchantDO> sysUserMerchantDOLambdaQueryWrapper = new LambdaQueryWrapper<>();
            sysUserMerchantDOLambdaQueryWrapper.eq(SysUserMerchantDO::getUserId, userPageResult.getId());
            SysUserMerchantDO sysUserMerchantDO = sysUserMerchantMapper.selectOne(sysUserMerchantDOLambdaQueryWrapper);
            pageDTO.setMerchantId(sysUserMerchantDO.getMerchantId());
            return pageDTO;
        }).toList();

        userPageDTO.setRecords(collect);
        userPageDTO.setTotal(userPage.getTotal());
        userPageDTO.setSize(userPage.getSize());
        userPageDTO.setCurrent(userPage.getCurrent());


        List<UserPageDTO> records = userPageDTO.getRecords();
        List<Long> sysUserIds = records.stream().map(UserPageDTO::getId).toList();
        List<String> teamIds = records.stream().map(UserPageDTO::getTeamIds).toList();
        //System.out.println("teamIds" + teamIds);

        // 处理teamIds将集合中的数据合并并去重,要注意teamIds中有些数据是使用“,”分割的有些不是
        // 使用Stream API去除null值
        List<String> filteredList = teamIds.stream()
                .filter(Objects::nonNull).distinct()
                .collect(Collectors.toList());


        if (!sysUserIds.isEmpty()) {

            // 获取到所有的teamId
            HashSet<Integer> allTeamId = new HashSet<>();
            Iterator<String> iterator1 = filteredList.iterator();
            while (iterator1.hasNext()) {
                String next = iterator1.next().trim();
                boolean contains = next.contains(",");
                if (!contains) {
                    allTeamId.add(Integer.valueOf(next));
                    continue;
                }
                String[] split = next.split(",");
                for (String s : split) {
                    String trim = s.trim();
                    allTeamId.add(Integer.valueOf(trim));
                }
            }

            List<Team> teams = teamService.listByIds(allTeamId);
            Map<Integer, Team> teamMap = teams.stream().collect(Collectors.toMap(Team::getId, obj -> obj));
            for (UserPageDTO record : records) {
                record.setReceivingStatusOpen(1);
                record.setIsWhechat(0);

                // 当前用户加入的团队的ID
                String teamIds1 = record.getTeamIds();
                int[] ids = null;

                if (teamIds1 != null) {
                    boolean contains = teamIds1.contains(",");
                    if (!contains) {
                        ids = new int[]{Integer.parseInt(teamIds1)};
                    } else {
                        String[] split = teamIds1.split(",");
                        ids = new int[split.length];
                        for (int i = 0; i < split.length; i++) {
                            ids[i] = Integer.parseInt(split[i]);
                        }
                    }
                } else {
                    ids = new int[0];
                }

                LambdaQueryWrapper<WechatUserSys> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(WechatUserSys::getSysUserId, record.getId())
                        .in(WechatUserSys::getTeamId, ids);
                long count = wechatUserSysService.count(queryWrapper);
                if (count > 1) {
                    record.setIsWhechat(1);
                }

                // 遍历teamMap 找到当前用户所在的所有组 一个用户可能在多个组中
                List<Team> teamList = new ArrayList<>();
                Set<Map.Entry<Integer, Team>> entries = teamMap.entrySet();
                Iterator<Map.Entry<Integer, Team>> iterator = entries.iterator();
                while (iterator.hasNext()) {
                    Map.Entry<Integer, Team> next = iterator.next();
                    Team value = next.getValue();
                    for (int i = 0; i < ids.length; i++) {
                        if (value.getId() == ids[i]) {
                            teamList.add(value);
                        }
                    }
                }

                // 对teamList进行去重
                List<Team> distTeamList = teamList.stream().distinct().toList();
                record.setTeams(distTeamList);
                List<SysRoleDO> roleDOS = getUserRoleId(record.getId());
                roleDOS = roleDOS.stream().distinct().toList();
                record.setRoles(roleDOS);
            }
        }
        return userPageDTO;
    }

    @Override
    public Page<UserMerchantInfoResult> getUserMerchantPage(UserMerchantPageCommand command) {
        BasePageDTO basePageDTO = basePageAssembler.formBasePageCommand(command);
        List<Long> merchantIds = getUserMerchantIds(SecurityUtils.X.getUser().getUserId());
        // 查询团队用户关联表
        List<Long> userIds = userTeamShipService.selectUserTeamShipByTeamIds(command.getTeamIds()).stream().map(UserTeamShip::getUserMerchantId).toList();
        if (command.getTeamIds() != null && userIds.isEmpty()) {
            return new Page<UserMerchantInfoResult>();
        }
        UserMerchantPageCondition condition = new UserMerchantPageCondition();
        condition.setKeywords(command.getKeywords());
        condition.setStatus(command.getStatus());
        condition.setMerchantIds(merchantIds);
        condition.setUserIds(userIds);
        condition.setPhone(command.getPhone());
        // 参数构建
        int pageNum = basePageDTO.getPageNum();
        int pageSize = basePageDTO.getPageSize();
        Page<User> page = new Page<>(pageNum, pageSize);
        // 查询数据
        Page<UserMerchantInfoResult> resultPage = sysUserMapper.getUserMerchantPage(page, condition);//,SystemConstants.BOKE_MERCHANT_ADMIN
        List<Long> sysUserIds = resultPage.getRecords().stream().map(UserMerchantInfoResult::getId).toList();
        if (CollUtil.isNotEmpty(sysUserIds)) {
            LambdaQueryWrapper<WechatUserSys> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.in(WechatUserSys::getSysUserId, sysUserIds);
            List<WechatUserSys> wechatUserSysList = wechatUserSysService.list(queryWrapper);
            Map<Integer, WechatUserSys> wechatUserSysMap = wechatUserSysList.stream().collect(Collectors.toMap(WechatUserSys::getSysUserId, obj -> obj));
            List<MerchantUserAccountDTO> results = merchantQueryAdminService.listMerchantUserAccountBySysUserIds(sysUserIds);
            Map<Long, MerchantUserAccountDTO> map = results.stream().collect(Collectors.toMap(MerchantUserAccountDTO::getSysUserId, Function.identity()));
            resultPage.getRecords().forEach(x -> {
                x.setIsWhechat(0);
                if (!ObjectUtils.isEmpty(wechatUserSysMap.get(x.getId()))) {
                    x.setIsWhechat(1);
                }
                //根据userId查询角色
                x.setRoleNames(sysUserMapper.getUserRoleName(x.getId()));
                // 查询用户所属团队
                Long id = x.getId();
                ArrayList<Team> userTeamShips = new ArrayList<>();
                StringBuilder userTeamNames = new StringBuilder();
                userTeamShipService.selectUserTeamShipByUserId(id).stream().map(UserTeamShip::getTeamId).toList().forEach(teamId -> {
                    Team team = teamService.selectTeamById(teamId);
                    userTeamShips.add(team);
                    if (StringUtils.isNotBlank(userTeamNames)) {
                        userTeamNames.append(";" + team.getTeamName());
                    } else {
                        userTeamNames.append(team.getTeamName());
                    }
                });
                x.setUserTeamShips(userTeamShips);
                x.setUserTeamNames(userTeamNames);
                x.setGenderLabel("女");
                if (x.getGender() == 1) {
                    x.setGenderLabel("男");
                }
                x.setReceivingStatus(0);
                x.setReceivingStatusOpen(0);
                MerchantUserAccountDTO response = map.get(x.getId());
                Optional.ofNullable(response).ifPresent(r -> {
                    x.setReceivingStatus(r.getReceivingStatus());
                    x.setRemark(r.getRemark());
                    x.setReceivingStatusOpen(1);
                });
            });
        }
        return resultPage;
    }

    @Override
    public AdminUser getUserInfoById(Long userId) {
        AdminUser adminUser = adminUserService.getById(userId);
        return adminUser;
    }

    @Override
    public UserOwnDetailDTO getOwnUserById(Long userId) {
        AdminUser adminUser = adminUserService.getById(userId);
        UserOwnDetailDTO userOwnDetailDTO = new UserOwnDetailDTO();
        BeanUtils.copyProperties(adminUser, userOwnDetailDTO);
        List<SysRoleDO> roleDOS = getUserRoleId(userOwnDetailDTO.getId().longValue());
        if (!ObjectUtils.isEmpty(roleDOS)) {
            userOwnDetailDTO.setRoles(roleDOS);
        }
        if (!ObjectUtils.isEmpty(adminUser.getDeptId())) {
            userOwnDetailDTO.setDeptName(adminDeptService.getById(adminUser.getDeptId()).getName());
        }
        boolean falg = false;
        for (SysRoleDO roleDO : roleDOS) {
            if (SecurityUtils.X.getRoleCodeExcepTelephoneList().contains(roleDO.getCode())) {
                falg = true;
                break;
            }
        }

        if (falg) {
            LambdaQueryWrapper<AdminUserTeamShip> teamShipLambdaQueryWrapper = new LambdaQueryWrapper<>();
            teamShipLambdaQueryWrapper.eq(AdminUserTeamShip::getUserMerchantId, userOwnDetailDTO.getId());
            List<AdminUserTeamShip> teamShipList = adminUserTeamShipService.list(teamShipLambdaQueryWrapper);
            List<Team> teams = teamService.getTeamListByUserId(userOwnDetailDTO.getId().longValue());
            Map<Integer, String> teamNameMap = teams.stream().collect(Collectors.toMap(Team::getId, obj -> obj.getTeamName()));
            Set<Integer> teamIds = teams.stream().map(i -> i.getId()).collect(Collectors.toSet());
            Map<Integer, Long> teamWechatMap = new HashMap<>();
            Map<Long, String> wechatInfoMap = new HashMap<>();
            if (!ObjectUtils.isEmpty(teamIds)) {
                LambdaQueryWrapper<WechatInfoTeam> wechatInfoTeamLambdaQueryWrapper = new LambdaQueryWrapper<>();
                wechatInfoTeamLambdaQueryWrapper.in(WechatInfoTeam::getTeamId, teamIds);
                List<WechatInfoTeam> infoTeamList = wechatInfoTeamService.list(wechatInfoTeamLambdaQueryWrapper);
                teamWechatMap = infoTeamList.stream().collect(Collectors.toMap(WechatInfoTeam::getTeamId, obj -> obj.getWechatInfoId()));
                if (!ObjectUtils.isEmpty(infoTeamList)) {
                    Set<Long> wechatIds = infoTeamList.stream().map(i -> i.getWechatInfoId()).collect(Collectors.toSet());
                    List<WechatInfo> wechatInfos = wechatInfoService.listByIds(wechatIds);
                    wechatInfoMap = wechatInfos.stream().collect(Collectors.toMap(WechatInfo::getId, obj -> obj.getCorpName()));
                }
            }
            for (AdminUserTeamShip adminUserTeamShip : teamShipList) {
                adminUserTeamShip.setTeamName(teamNameMap.get(adminUserTeamShip.getTeamId()));
                Long wechatId = teamWechatMap.get(adminUserTeamShip.getTeamId());
                if (!ObjectUtils.isEmpty(wechatId)) {
                    adminUserTeamShip.setCorpName(wechatInfoMap.get(wechatId));
                }
            }
            userOwnDetailDTO.setTeamShipList(teamShipList);
        }
        return userOwnDetailDTO;
    }

    @Override
    public UserDetailDTO getUserInfoByIdAndTeamId(Long userId) {
        UserInfoResult userInfoResult = sysUserMapper.getUserInfoByIdAndTeamId(userId);

        String teamIds = userInfoResult.getTeamIds();

        List<Long> teamIdList = new ArrayList<>();
        if (!teamIds.contains(",")) {
            teamIdList.add(Long.parseLong(teamIds));
        }

        String[] split = teamIds.split(",");
        // 将拆分后的字符串转换为整数
        for (String s : split) {
            teamIdList.add(Long.parseLong(s));
        }
        List<AddUserTeamCommand> addUserTeamCommands = new ArrayList<>();
        Iterator<Long> iterator = teamIdList.iterator();
        while (iterator.hasNext()) {
            Long teamId = iterator.next();
            LambdaQueryWrapper<UserTeamShip> userTeamShipLambdaQueryWrapper = new LambdaQueryWrapper<>();
            userTeamShipLambdaQueryWrapper.eq(UserTeamShip::getTeamId, teamId)
                    .eq(UserTeamShip::getUserMerchantId, userId);
            UserTeamShip one = userTeamShipService.getOne(userTeamShipLambdaQueryWrapper);
            // 封装AddUserTeamCommand
            AddUserTeamCommand addUserTeamCommand = new AddUserTeamCommand();

            List<AdminUserTeamShip> adminUserTeamShipList = adminUserTeamShipService.getListByUserId(userId.intValue());
            Map<Integer, AdminUserTeamShip> adminUserTeamShipMap = adminUserTeamShipList.stream().collect(Collectors.toMap(AdminUserTeamShip::getTeamId, obj -> obj));

            // teamId转换成Integer类型
            AdminUserTeamShip adminUserTeamShip = adminUserTeamShipMap.get(teamId.intValue());
            if (!ObjectUtils.isEmpty(adminUserTeamShip) && !ObjectUtils.isEmpty(adminUserTeamShip.getWhechatAccount())) {
                addUserTeamCommand.setBindingWechat(1);
                addUserTeamCommand.setWhechatMobile(adminUserTeamShip.getWhechatAccount());
            } else {
                addUserTeamCommand.setBindingWechat(0);
                addUserTeamCommand.setWhechatMobile(adminUserTeamShip.getWhechatAccount());
            }



            addUserTeamCommand.setTeamId(teamId);
            addUserTeamCommand.setReceivingStatus(one.getReceivingStatus());
            addUserTeamCommands.add(addUserTeamCommand);
        }

//        UserDetailDTO dto = userAssembler.toUserDetailDTO(userInfoResult);

        UserDetailDTO userDetailDTO = new UserDetailDTO();
        BeanUtils.copyProperties(userInfoResult, userDetailDTO);
        addUserTeamCommands = addUserTeamCommands.stream().distinct().toList();
        userDetailDTO.setUserTeamCommands(addUserTeamCommands);

        List<SysRoleDO> roleDOS = getUserRoleId(userDetailDTO.getId());
        if (!ObjectUtils.isEmpty(roleDOS)) {
            userDetailDTO.setRoles(roleDOS);
        }
        List<Team> teams = teamService.listByIds(teamIdList);
        List<AdminUserTeamShip> adminUserTeamShipList = adminUserTeamShipService.getListByUserId(userId.intValue());
        Map<Integer, AdminUserTeamShip> adminUserTeamShipMap = adminUserTeamShipList.stream().collect(Collectors.toMap(obj -> obj.getTeamId(), obj -> obj));
        for (Team team : teams) {
            AdminUserTeamShip adminUserTeamShip = adminUserTeamShipMap.get(team.getId());
            if (!ObjectUtils.isEmpty(adminUserTeamShip) && !ObjectUtils.isEmpty(adminUserTeamShip.getWhechatAccount())) {
                team.setBindingWechat(1);

            } else {
                team.setBindingWechat(0);
            }
        }
        userDetailDTO.setTeams(teams);
        return userDetailDTO;
    }

    @Override
    public UserAuthInfoResult getUserAuthInfo(String queryValue, Integer queryType) {
        UserAuthInfoResult userAuthInfoResult = sysUserMapper.getUserAuthInfo(queryValue, queryType);
        if (userAuthInfoResult != null) {
            Set<String> roles = userAuthInfoResult.getRoles();
            if (CollUtil.isNotEmpty(roles)) {
                Set<String> perms = menuQueryService.listRolePerms(roles);
                userAuthInfoResult.setPerms(perms);
            }
            // 获取最大范围的数据权限
            Integer dataScope = sysRoleMapper.getMaximumDataScope(roles);
            userAuthInfoResult.setDataScope(dataScope);
        }
        return userAuthInfoResult;
    }


    @Override
    public List<UserExportDTO> listExportUsers(UserPageCommand command) {
        UserPageCondition condition = userAssembler.formUserPageCondition(command);
        List<UserExportResult> results = sysUserMapper.listExportUsers(condition);
        return results.stream().map(userAssembler::toUserExportDTO).toList();
    }

    @Override
    public UserInfoDTO getUserLoginInfo() {
        // 登录用户entity
        UserSimple user = userRepository.getUserSimpleByUsername(SecurityUtils.X.getUser().getUsername());
        UserInfoDTO userInfoDTO = userAssembler.toUserInfoDTO(user);
        // 用户角色集合
        Set<String> roles = SecurityUtils.X.getRoles();
        userInfoDTO.setRoles(roles);
        // 用户权限集合
        Set<String> perms = (Set<String>) redisTemplate.opsForValue().get(SecurityConstants.USER_PERMS_CACHE_PREFIX + user.getId());
        userInfoDTO.setPerms(perms);
        return userInfoDTO;
    }

    @Override
    public List<Long> getUserMerchantIds(Long userId) {
        return sysUserMerchantMapper.listMerchantIdsByUserId(userId);
    }

    @Override
    public Long getUserLoginInfoByPhone(String phone) {
        SysUserDO sysUserDO = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUserDO>().eq(SysUserDO::getMobile, phone));
        if (Objects.isNull(sysUserDO)) {
            return null;
        }
        return sysUserDO.getId();
    }

    @Override
    public SysUserDO selectUserInfoByPhone(String phone) {
        SysUserDO sysUserDO = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUserDO>().eq(SysUserDO::getMobile, phone));
        return sysUserDO;
    }

    /**
     * 查询当前商户下的用户集合(只查询开启状态)
     *
     * @param userId
     * @return
     */
    @Override
    public List<Long> getMerchantUserIds(Long userId) {
        return sysUserMerchantMapper.getMerchantUserIds(userId);
    }

    /**
     * 查询用户角色
     *
     * @param userId
     * @return
     */
    @Override
    public List<SysRoleDO> getUserRoleId(Long userId) {
        return sysUserMapper.getUserRoleId(userId);
    }
}
